/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package systole.view.charts;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

/**
 *
 * @author user
 */
public class XYChart {

    private JFreeChart chart;
    private XYSeriesCollection seriesCollection;
    private XYPlot subplot;
    private XYItemRenderer renderer;
    private boolean showLegend = true;
    private boolean showTitle = true;
    private String title;
    private String xLabel;
    private String yLabel;
    private HashMap<String, Integer> seriesMap;
    private static final double Y_PADDING = 1.0f;

    /**
     * @param title
     * @param x_label
     * @param y_label
     */
    public XYChart(String title, String x_label, String y_label) {
        this.title = title;
        this.xLabel = x_label;
        this.yLabel = y_label;

        this.seriesCollection = new XYSeriesCollection();
        this.seriesMap = new HashMap<String, Integer>();


    }

    /**
     * @param title
     */
    public XYChart(String title) {
        this.title = title;
        this.xLabel = null;
        this.yLabel = null;

        this.seriesCollection = new XYSeriesCollection();
        this.seriesMap = new HashMap<String, Integer>();
    }

    /**
     *
     * @param allBlackAndWhite
     */
    private void createChart(boolean allBlackAndWhite) {

        this.renderer = new StandardXYItemRenderer();
        NumberAxis range = new NumberAxis(this.yLabel);
        NumberAxis domain = new NumberAxis(this.xLabel);

        //Determino los valores maximos y minimos en el eje y para el grafico (para no redimensionar)
        XYSeries main = this.seriesCollection.getSeries(0);
        double upperBound = main.getMaxY() + XYChart.Y_PADDING;
        range.setLowerBound(main.getMinY());
        range.setUpperBound(upperBound);


        this.subplot = new XYPlot(this.seriesCollection, domain, range, this.renderer);
        this.subplot.setOrientation(PlotOrientation.VERTICAL);
        if (allBlackAndWhite) {
            this.subplot.getRenderer().setSeriesPaint(0, Color.BLACK);
        }

        this.setChartModel(new JFreeChart((this.showTitle) ? this.title : null, null, this.subplot, this.isShowLegend()));
        this.getChartModel().getXYPlot().setBackgroundPaint(Color.WHITE);
        if (allBlackAndWhite) {
            this.getChartModel().setBackgroundPaint(Color.white);
        }
    }

    /**
     * @param seriesName
     * @param dataset
     * @param xFactor
     */
    public void addSeries(String seriesName, double[] dataset, double xFactor) {

        XYSeries serie = new XYSeries(seriesName);
        for (int i = 0; i < dataset.length; i++) {
            serie.add(i * xFactor, dataset[i], (i == dataset.length - 1));
        }

        this.seriesMap.put(seriesName, this.seriesCollection.getSeriesCount());
        this.seriesCollection.addSeries(serie);
    }

    /**
     * @param seriesIndex
     * @param color
     */
    public void setSeriesColor(int seriesIndex, Color color) {

        this.getChartModel().getXYPlot().getRenderer().setSeriesPaint(seriesIndex, color);
    }

    /**
     *
     * @param seriesName
     */
    public void toggleSeries(String seriesName) {

        int seriesPosition = this.seriesMap.get(seriesName).intValue();
        boolean flag = this.renderer.getSeriesVisible(seriesPosition);
        this.renderer.setSeriesVisible(seriesPosition, new Boolean(!flag), true);

    }

    /**
     * Muestra el cursor del eje X como una linea fija en el eje de abcisas
     *
     * @param show
     */
    public void showXCrosshair(boolean show) {
        this.subplot.setDomainCrosshairVisible(show);
    }

    /**
     * Muestra el cursor del eje Y como una linea fija en el eje de ordenadas
     *
     * @param show
     */
    public void showYCrosshair(boolean show) {
        this.subplot.setRangeCrosshairVisible(show);
    }

    /**
     * @return Panel Chart
     */
    public ChartPanel plot() {
        this.createChart(false);
        ChartPanel cPanel = new ChartPanel(this.getChartModel());
        return cPanel;
    }

    /**
     *
     * @return  Black and white panel
     **/
    public ChartPanel blackAndWhitePlot() {
        ChartPanel bwPanel = this.plot();
        bwPanel.getChart().setBackgroundPaint(Color.WHITE);
        bwPanel.getChart().getXYPlot().setBackgroundPaint(Color.WHITE);
        bwPanel.getChart().getXYPlot().getRenderer().setSeriesPaint(0, Color.BLACK);
        return bwPanel;
    }

    /**
     * @param width
     * @param height
     * @param blackNadWhite
     * @return plot Image
     */
    public BufferedImage plotThumbnail(int width, int height, boolean blackNadWhite) {
        this.createChart(blackNadWhite);
        return this.chart.createBufferedImage(width, height, BufferedImage.TYPE_INT_ARGB, null);
    }

    /**
     * @return if show legend
     */
    public boolean isShowLegend() {
        return showLegend;
    }

    /**
     * @param showLegend
     */
    public void setShowLegend(boolean showLegend) {
        this.showLegend = showLegend;
    }

    public int getSeriesIndex(String description) {
        return this.seriesMap.get(description).intValue();
    }

    public XYSeries getSeries(String description) {
        return this.seriesCollection.getSeries(description);
    }

    public ArrayList<String> getKeys() {

        ArrayList<String> keys = new ArrayList<String>();
        Iterator<String> it = this.seriesMap.keySet().iterator();

        while (it.hasNext()) {
            keys.add(it.next());
        }

        return keys;
    }

    /**
     * @return the showTitle
     */
    public boolean isShowTitle() {
        return showTitle;
    }

    /**
     * @param showTitle the showTitle to set
     */
    public void setShowTitle(boolean showTitle) {
        this.showTitle = showTitle;
    }

    /**
     * @return the chart
     */
    public JFreeChart getChartModel() {
        return chart;
    }

    /**
     * @param chart the chart to set
     */
    public void setChartModel(JFreeChart chart) {
        this.chart = chart;
    }
}
